package com.boarsoft.boar.oss.util;

import com.boarsoft.bean.ReplyInfo;
import com.obs.services.ObsClient;
import com.obs.services.exception.ObsException;
import com.obs.services.model.ObsObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

/**
 * @author tao.wang57
 * @desc 下载对象工具类<p>
 * @date 2023-03-25 pm
 */
public class DownloadObjectUtil {

    private static final Logger log = LoggerFactory.getLogger(DownloadObjectUtil.class);

    /**
     * @param obsClient
     * @param bucketName 桶名。
     *                   约束限制：<br>
     *                   桶的名字需全局唯一，不能与已有的任何桶名称重复，包括其他用户创建的桶。<br>
     *                   桶命名规则如下：<br>
     *                   3～63个字符，数字或字母开头，支持小写字母、数字、“-”、“.”。<br>
     *                   禁止使用IP地址。<br>
     *                   禁止以“-”或“.”开头及结尾。<br>
     *                   禁止两个“.”相邻（如：“my..bucket”）。<br>
     *                   禁止“.”和“-”相邻（如：“my-.bucket”和“my.-bucket”）。<br>
     *                   同一用户在同一个区域多次创建同名桶不会报错，创建的桶属性以第一次请求为准。<br>
     * @param objectName objectKey + "/" + fileName<br>
     *                   例如，您对象的访问地址为examplebucket.obs.cn-north-4.myhuaweicloud.com/folder/test.txt 中，
     *                   对象名为folder/test.txt。
     * @return
     */
    public static InputStream download(ObsClient obsClient, String bucketName, String objectName) {
        ByteArrayOutputStream bos = null;
        InputStream input = null;
        try {
            // 流式下载
            ObsObject obsObject = obsClient.getObject(bucketName, objectName);
            // 读取对象内容
            //System.out.println("Object content:");
            input = obsObject.getObjectContent();
//            byte[] b = new byte[1024];
//            bos = new ByteArrayOutputStream();
//            int len;
//            while ((len = input.read(b)) != -1) {
//                bos.write(b, 0, len);
//            }
            log.info("getObjectContent successfully");
//            log.info(new String(bos.toByteArray()));
        } catch (ObsException e) {
            log.error("getObjectContent failed", e);
            printObsException(e);
        } catch (Exception e) {
            // 其他异常信息打印
            log.error("getObjectContent failed", e);
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            closeClient(obsClient);
        }
        return input;
    }

    /**
     * 下载文件到本地指定的位置
     *
     * @param obsClient
     * @param bucketName
     * @param objectName
     * @param localPath     本地路径 如 home/admin/temp
     * @param localFileName 文件名称 如 test.txt
     * @return
     */
    public static ReplyInfo<Object> download(ObsClient obsClient, String bucketName, String objectName, String localPath, String localFileName) {
        InputStream input = download(obsClient, bucketName, objectName);
        BufferedInputStream in = null;
        BufferedOutputStream out = null;
        try {
            String fileName = localPath + File.separator + localFileName;
            File file = new File(fileName);
            if (!file.exists()) {
                file.createNewFile();
            }
            in = new BufferedInputStream(input);
            out = new BufferedOutputStream(new FileOutputStream(fileName));
            int len = -1;
            byte[] b = new byte[1024];
            while ((len = in.read(b)) != -1) {
                out.write(b, 0, len);
            }
        } catch (Exception e) {
            log.error("下载文件异常", e);
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            try {
                out.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            closeClient(obsClient);
        }
        return ReplyInfo.SUCCESS;
    }

    private static void closeClient(ObsClient obsClient) {
        if (obsClient != null) {
            try {
                obsClient.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    private static void printObsException(ObsException e) {
        // 请求失败,打印http状态码
        log.error("HTTP Code:" + e.getResponseCode());
        // 请求失败,打印服务端错误码
        log.error("Error Code:" + e.getErrorCode());
        // 请求失败,打印详细错误信息
        log.error("Error Message:" + e.getErrorMessage());
        // 请求失败,打印请求id
        log.error("Request ID:" + e.getErrorRequestId());
        log.error("Host ID:" + e.getErrorHostId());
    }

}
